package com.xqboss.apps.service.punch;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xqboss.apps.domain.punch.PunchRule;
import com.xqboss.apps.dto.punch.AddPunchRuleDto;
import com.xqboss.apps.mapper.punch.PunchRuleMapper;
import com.xqboss.apps.util.mh.BeanCopierUtil;
import com.xqboss.common.exception.ServiceException;
import com.xqboss.common.utils.StringUtils;
import com.xqboss.common.utils.bean.BeanUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * <p>
 *     打卡规则服务
 * </p>
 * @author Trent
 * @date 2023/8/15
 */
@Service
public class PunchRuleService extends ServiceImpl<PunchRuleMapper, PunchRule> {

    @Autowired
    private PunchUserConfigService punchUserConfigService;

    public PunchRule requireSaleableRule(Long ruleId){
        PunchRule rule = getById(ruleId);
        if(rule == null || BooleanUtils.isNotTrue(rule.getSaleable())){
            throw new ServiceException("打卡规则不存在！");
        }
        return rule;
    }

    /**
     * 获取打卡规则列表
     *
     * @param saleable 上下架状态
     * @param keyword 搜索关键字
     * @return
     */
    public List<PunchRule> getList(Boolean saleable, String keyword){
        LambdaQueryWrapper<PunchRule> queryWrapper = new LambdaQueryWrapper<>();
        if(Objects.nonNull(saleable)){
            queryWrapper.eq(PunchRule::getSaleable, saleable);
        }
        if(StringUtils.isNotEmpty(keyword)){
            queryWrapper.like(PunchRule::getName, keyword);
        }
        return list(queryWrapper);
    }

    /**
     * 添加打卡规则
     * @param params
     */
    public void addRule(AddPunchRuleDto params) {
        // 计算间隔时间是否异常
        if(!params.getEndTime().isAfter(params.getStartTime())){
            throw new ServiceException("结束时间必须在开始时间之后");
        }
        int totalSecond = params.getEndTime().toSecondOfDay() - params.getStartTime().toSecondOfDay();
        if(Objects.nonNull(params.getIntervalTime())){
            if(params.getIntervalTime() < 5){
                throw new ServiceException("间隔时间最低5秒！");
            }
            if(params.getIntervalTime() * params.getPunchCount() > totalSecond){
                throw new ServiceException("间隔时间应该小于" + (totalSecond / params.getPunchCount()) + "秒");
            }
        }else{
            if(totalSecond % params.getPunchCount() != 0){
                throw new ServiceException("该次数无法均分该时间段");
            }
            // 计算时间段
            int intervalTime = totalSecond / params.getPunchCount();
            if(intervalTime < 5){
                throw new ServiceException("最低5秒间隔时间！");
            }
            params.setIntervalTime(intervalTime);
        }

        PunchRule rule = BeanCopierUtil.copy(params, PunchRule.class);
        save(rule);
    }

    public void editRule(Long id, AddPunchRuleDto params) {
        PunchRule rule = getById(id);
        Objects.requireNonNull(rule, "资源不存在！");
        // 计算间隔时间是否异常
        if(!params.getEndTime().isAfter(params.getStartTime())){
            throw new ServiceException("结束时间必须在开始时间之后");
        }
        int totalSecond = params.getEndTime().toSecondOfDay() - params.getStartTime().toSecondOfDay();
        if(Objects.nonNull(params.getIntervalTime())){
            if(params.getIntervalTime() < 5){
                throw new ServiceException("间隔时间最低5秒！");
            }
            if(params.getIntervalTime() * params.getPunchCount() > totalSecond){
                throw new ServiceException("间隔时间应该小于" + (totalSecond / params.getPunchCount()) + "秒");
            }
        }else{
            if(totalSecond % params.getPunchCount() != 0){
                throw new ServiceException("该次数无法均分该时间段");
            }
            // 计算时间段
            int intervalTime = totalSecond / params.getPunchCount();
            if(intervalTime < 5){
                throw new ServiceException("最低5秒间隔时间！");
            }
            params.setIntervalTime(intervalTime);
        }
        BeanUtils.copyProperties(params, rule);
        updateById(rule);
    }


    /**
     * 获取所有的上架列表
     * @return
     */
    public List<PunchRule> getAllSaleableList() {
        return list(new LambdaQueryWrapper<PunchRule>()
                .eq(PunchRule::getSaleable, true)
                .orderByAsc(PunchRule::getSort)
                .orderByDesc(PunchRule::getId));
    }

    /**
     * 修改上下架状态
     * @param id
     * @param saleable
     */
    public void changeSaleable(Long id, Boolean saleable) {
        // 获取当前上架的规则
        PunchRule rule = getById(id);
        Objects.requireNonNull(rule, "规则不存在！");
        if (rule.getSaleable().equals(saleable)) {
            return;
        }
        if (saleable) {
            // 如果是上架，则判断时间是否冲突
            // 获取当前已经上架的列表
            List<PunchRule> list = list(new LambdaQueryWrapper<PunchRule>().eq(PunchRule::getSaleable, true));
            for (PunchRule punchRule : list) {
                if (punchRule.getEndTime().equals(rule.getEndTime()) && punchRule.getStartTime().equals(rule.getStartTime())) {
                    // 如果两个时间段都一致，而且打卡次数一致，则不能上架
                    if (Objects.equals(rule.getPunchCount(), punchRule.getPunchCount())) {
                        throw new ServiceException("与已上架规则重复");
                    }
                }
            }
        } else {
            // 如果是下架，则清除用户的打卡配置
            punchUserConfigService.cleanPunchRule(id);
        }

        boolean update = update(new LambdaUpdateWrapper<PunchRule>()
                .set(PunchRule::getSaleable, saleable)
                .eq(PunchRule::getId, id));
        if (!update) {
            throw new ServiceException("操作失败！");
        }
    }
}
